package microcredit.db;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import microcredit.DatabaseUtilities;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
import org.apache.ddlutils.model.Table;

public class ImportExportByTable implements IImportExport{

	private static final Log LOGGER = LogFactory.getLog(ImportExportByTable.class);
	
	private static final String VERSION_FILE_NAME = "VERSION.TXT";
	private Platform p;
	private Connection conn;
	
	private boolean deleteDirectory(File path) {
		if( path.exists() ) {
			File[] files = path.listFiles();
			for(int i=0; i<files.length; i++) {
				if(files[i].isDirectory()) {
					deleteDirectory(files[i]);
				}
				else {
					files[i].delete();
				}
			}
		}
		return( path.delete() );
	}

	
	private void importFromFolder(File folder) throws SQLException, FileNotFoundException, IOException {
		File versionFile = new File(folder, VERSION_FILE_NAME);
		Properties prop = new Properties();
		prop.load(new FileInputStream(versionFile));
//		String version = (String)prop.get("version");
//		if (!Version.VERSION.equals(version)) {
//			throw new FileNotFoundException("Could not import database! database version: "+version+" current version: "+Version.VERSION+". The database versions must match!");
//		}
		Database db = p.readModelFromDatabase("APP");
		PreparedStatement ps= conn.prepareStatement(
    		"CALL SYSCS_UTIL.SYSCS_IMPORT_TABLE  (?,?,?,?,?,?,?)");
		for (Table table : db.getTables()) {
			File targetFile = new File(folder, table.getName()+".DAT");
			LOGGER.info("import " + table.getName());
			if (targetFile.exists()) {
			    ps.setString(1,null);
			    ps.setString(2, table.getName());
			    ps.setString(3, targetFile.getAbsolutePath());
			    ps.setString(4, ";");
			    ps.setString(5,null);
			    ps.setString(6,null);
			    ps.setString(7, "1");
			    ps.execute();
			} else {
				PreparedStatement dropStmt = conn.prepareStatement("delete from "+table.getName());
				dropStmt.execute();
				dropStmt.close();
			}
		}
		ps.close();
	}
	
	@Override
	public void importDatabase(File importfile) throws Exception {
		File tmpFolder = new File("./tmp/import");
		try {
			tmpFolder.mkdirs();
			DatabaseUtilities.getInstance().unzipFolder(importfile, tmpFolder);
			
		} finally {
			Factory.initFactoryNew();
			deleteDirectory(tmpFolder);
		}
	}
	
	@Override
	public void exportDatabase(File targetFile) throws Exception {
		open();
		File tmpFolder = new File("./tmp/export");
		try {
			tmpFolder.mkdirs();
			exportIntoFolder(tmpFolder);
			DatabaseUtilities.getInstance().zipFolder(tmpFolder, targetFile);
		}  finally {
			conn.rollback();
			conn.close();
			
			for (File f : tmpFolder.listFiles()) {
				f.delete();
			}
			tmpFolder.delete();
		}
	}
	
	private void exportIntoFolder(File folder) throws Exception {
		Database db = p.readModelFromDatabase("APP");
		PreparedStatement ps= conn.prepareStatement(
	    	"CALL SYSCS_UTIL.SYSCS_EXPORT_TABLE (?,?,?,?,?,?)");
		for (Table table : db.getTables()) {
			File targetFile = new File(folder, table.getName()+".DAT");
			if (targetFile.exists()) {
				targetFile.delete();
			}
			PreparedStatement stmt = conn.prepareStatement("select count(*) from "+table.getName());
			ResultSet resultSet = stmt.executeQuery();
			resultSet.next();
			int size = resultSet.getInt(1);
			if (size == 0) {
				continue;
			}
			
			LOGGER.info("export "+table.getName()+" lines "+size);
		    ps.setString(1,null);
		    ps.setString(2, table.getName());
		    ps.setString(3, targetFile.getAbsolutePath());
		    ps.setString(4, ";");
		    ps.setString(5,null);
		    ps.setString(6,null);
		    ps.execute();
		}
		ps.close();
		
		String version = Factory.readVersion(conn);
		
		Properties prop = new Properties();
		prop.put("version", version);
		File versionFile = new File(folder, VERSION_FILE_NAME);
		if (versionFile.exists()) {
			versionFile.delete();
		}
		
		FileOutputStream stream = new FileOutputStream(versionFile);
		prop.store(stream, "Version file for the database");
		stream.close();
	}
	
	private void open() throws Exception {
		p = Factory.createDefaultPlatform();
		conn = p.getDataSource().getConnection();
	}
	
	public static void main(String[] args) throws Exception {
		Factory.initFactoryNew();
		Factory.getFactory().close();
		
		ImportExportByTable importExport = new ImportExportByTable();
		File f = new File("./asdf.zip");
		importExport.exportDatabase(f);
		importExport.importDatabase(f);
	}
}
